<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>柱状图</title>
    <style>
        body {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <div id="container"></div>
</body>
<script src="https://unpkg.com/konva@6.0.0/konva.min.js"></script>
<script>
    (function () {
        let width = window.innerWidth;
        let height = window.innerHeight;

        let stage = new Konva.Stage({
            container: 'container',
            width: width,
            height: height
        })
        let cenX = width / 2;
        let cenY = height / 2;
        let layer = new Konva.Layer();
        stage.add(layer);

        let data = [
            { name: '前端', value: 45, color: '#274' },
            { name: 'PHP', value: 64, color: '#a25' },
            { name: 'Java', value: 22, color: '#ca5' },
            { name: 'UI', value: 89, color: '#198' },
            { name: 'Android', value: 36, color: '#a0e' },
        ];
        // data = [
        //     { name: '前端', value: .8, color: 'green' },
        //     { name: 'PHP', value: .3, color: 'blue' },
        //     { name: 'Java', value: .7, color: 'red' },
        //     { name: 'UI', value: .9, color: 'orange' },
        //     { name: 'IOS', value: .4, color: 'purple' },
        //     { name: 'Android', value: .9, color: 'pink' }
        // ];
        let x0 = width / 8,
            y0 = height * 3 / 4,
            w0 = (width * 3 / 4),
            h0 = height / 2;
        //总数
        let sum = 0;
        data.forEach(item => { sum += item.value })
        sum = 100;
        let sumText = new Konva.Text({
            x: x0,
            y: y0 - h0,
            text: sum,
            fill: 'red',
            fontSize: 20
        })
        sumText.x(sumText.x() - sumText.getWidth() - 10)
        layer.add(sumText)

        //底线
        let line = new Konva.Line({
            x: x0,
            y: y0,
            points: [0, 0 - h0, 0, 0, w0, 0],
            stroke: 'red',
        })
        layer.add(line);
        //柱状图组
        let rectGroup = new Konva.Group({
            x: x0,
            y: y0,
        })
        //数值组
        let textGroup = new Konva.Group({
            x: x0,
            y: y0,
        })
        let textBottomGroup = new Konva.Group({
            x: x0,
            y: y0,
        })
        data.forEach((item, index) => {
            let h = item.value / sum * h0;
            let rw = w0 / data.length;
            let gx = rw * (1 / 4 + index)
            // 绘制柱状图 
            let rect = new Konva.Rect({
                x: gx,
                y: -h,
                width: rw / 2,
                height: h,
                fill: item.color,
                cornerRadius: [10, 10, 0, 0],
                shadowBlur: 20,
                shadowColor: '#999',
            })
            rectGroup.add(rect);
            // 绘制数值
            let text = new Konva.Text({
                x: rw * index,
                y: -h - 20,
                width: rw,
                align: 'center',
                text: `${(item.value / sum * 100).toFixed(2)}%`,
                fill: item.color,
                fontSize: 16,
            })
            textGroup.add(text)
            //绘制文本
            let textBottom = new Konva.Text({
                x: rw * (index + 1 / 4),
                y: 10,
                width: rw,
                text: item.name,
                fill: item.color,
                rotation: 30,
                fontSize: 20,
            })
            textBottomGroup.add(textBottom)
        })
        layer.add(rectGroup)
        layer.add(textGroup)
        layer.add(textBottomGroup)
        layer.draw();

        //动画系统
        let duration = 1
        rectGroup.getChildren().each((item, index) => {
            item.height(0)
            item.y(0)
            item.to({
                y: -(data[index].value / sum * h0),
                height: data[index].value / sum * h0,
                duration: duration
            })
        })
        textGroup.getChildren().each((item, index) => {
            item.y(0 - 20);
            item.to({
                y: -(data[index].value / sum * h0) - 20,
                duration: duration
            })
        })
    }())
</script>

</html>